﻿#pragma once

#include "geom_curve.h"

namespace CAGD
{

/**
 * @brief 直线.
 *
 */
template <int Dim> class GeomLineDim : public GeomCurveDim<Dim>
{
  public:
    /**
     * @brief 两点构造.
     * @param p1
     * @param p2
     * @see
     */
    GeomLineDim(BPntN<Dim> p1, BPntN<Dim> p2) : m_p(p1), m_dir((p2 - p1).Normalized())
    {
    }

    /**
     * @brief 点向构造.
     * @param p1
     * @param dir
     * @see
     */
    GeomLineDim(BPntN<Dim> p1, BVecN<Dim> dir) : m_p(p1), m_dir(dir)
    {
    }

    /**
     * @brief 起始参数.
     * @return
     * @see
     */
    double FirstParamter() const override
    {
        return -FLT_MAX;
    }

    /**
     * @brief 终止参数.
     * @return
     * @see
     */
    double LastParamter() const override
    {
        return FLT_MAX;
    }

    /**
     * @brief 取值函数.
     * @param t
     * @param P
     * @see
     */
    void D0(double t, BPntN<Dim> &P) const override
    {
        P = m_p + m_dir * t;
    }

    /**
     * @brief 切向函数.
     * @param t
     * @param P
     * @param V1
     * @see
     */
    void D1(double t, BPntN<Dim> &P, BVecN<Dim> &V1) const override
    {
        P = m_p + m_dir * t;
        V1 = m_dir;
    }

    /**
     * @brief 2 阶导函数.
     * @param t
     * @param P
     * @param V1
     * @param V2
     * @see
     */
    void D2(double t, BPntN<Dim> &P, BVecN<Dim> &V1, BVecN<Dim> &V2) const override
    {
        P = m_p + m_dir * t;
        V1 = m_dir;
        V2 = BVecN<Dim>();
    }

    /**
     * @brief n 阶导函数.
     * @param N
     * @param t
     * @param P
     * @param V
     * @see
     */
    void DN(int N, double t, BPntN<Dim> &P, std::vector<BVecN<Dim>> &V) const override
    {
        P = m_p + m_dir * t;
        V.push_back(m_dir);
        for (int i = 2; i < N; i++)
            V.push_back(BVecN<Dim>());
    }

    /**
     * @brief 获得引用点.
     * @return
     * @see
     */
    std::vector<BPntN<Dim> *> MakeReference() override
    {
        std::vector<BPntN<Dim> *> reference;
        return reference;
    }

  protected:
    BPntN<Dim> m_p;
    BVecN<Dim> m_dir;
};

using Geom2dLine = GeomLineDim<2>;
using GeomLine = GeomLineDim<3>;

} // namespace CAGD
